import java.io.*;
import java.util.Map;
import java.util.concurrent.BlockingQueue;

public class RcvFileWriteModule {

}
class RcvFileWriteThread implements Runnable{
    static {
        //在类加载时就创建线程
        //只有这个线程可以访问这个单例的所有属性~~
        System.out.println("RcvFileWriteThread文件块写入磁盘线程开始执行");
        new Thread(new RcvFileWriteThread(), "RcvFileWriteThread0").start();
        //单消费者,N个生产者,emmmm不知道消息队列会不会承受不住,要不开两个??反正这个线程开多几个也没问题的
    }

    @Override
    public void run() {
        //1.从 "文件接收队列" 拿出 byte[]数组
        BlockingQueue<byte[]> rcv_file_queue = ReciveFileQueue.getQueue();
        while (true){
            try {
                //1.1真正拿出的"take"是阻塞
                byte[] chunk = rcv_file_queue.take();//此时接收到的文件队列已经是没有"文件块头部大小"的首部的了(NetChunkUtil.recive)负责去除块首部,只返回"内容"(这里我分层解耦设计得非常好)
                //2.读取byte[]数组的头部信息,得知 文件块 所属的 "整个文件的MD5值"   (读取的是"文件切片"时放入的头部)
                //2.1分别读取chunk的各个区域
                byte[] MD5_whole_file_byte = new byte[16];//完整文件的md5值(不是文件片的md5)(因为使用TCP传输,似乎差错校验也没必要做了)
                byte[] seq_byte = new byte[4];//序号
                byte[] file_chunk = new byte[chunk.length - 20];//文件片二进制数据
                System.arraycopy(chunk,0,MD5_whole_file_byte,0,16);
                System.arraycopy(chunk,16,seq_byte,0,4);
                System.arraycopy(chunk,20,file_chunk,0,chunk.length - 20);
                //2.2把首部字段解析出来
                String MD5_whole_file_str = Md5CaculateUtil.MD5ArrFromHexToString(MD5_whole_file_byte);
                int seq_num = NetChunkUtil.byteArrayToInt(seq_byte);

                //3.把文件块写入磁盘对应的文件夹
                //3.1创建文件夹
                String class_path = RcvFileWriteModule.class.getResource("/").getPath();
                File chunk_floder = new File(class_path + MD5_whole_file_str);//文件夹的路径
                if (!chunk_floder.isDirectory()) {//判断这个名字的文件夹是否存在,如果存在就无需创建了
                    if (!chunk_floder.mkdirs()) {
                        System.out.println("创建文件片存储文件夹失败");
                        return;
                    }
                }
                //3.2在文件夹里写入,文件名就是一个数字
                try {
                    String file_chunk_path = chunk_floder.getPath() + File.separator + seq_num;
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file_chunk_path));
                    bos.write(chunk);//直接写入chunk就行,已经在FileSplitMerge里面做了去掉头部的处理
                    bos.flush();//老是忘记flush!!!!
                    //4.修改 "FileHoldingListSelf对象" 的内容
                    //目前这个对象还没有创建者.......所以暂时无法测试
                /*Map<String, FileHoldingListSelf> file_hold_list_self_map = FileHoldingListSelfMap.getMap();//从全局管理Map中获取这个FileHoldingListSelf
                FileHoldingListSelf FHLS = file_hold_list_self_map.get(MD5_whole_file_str);
                FHLS.file_chunk_list[seq_num].is_hold = true;
                FHLS.file_chunk_list[seq_num].addr = file_chunk_path;

                 */
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}